package logic

import (
	"common/global"
	"context"
	"encoding/json"
	"equipment_server/model"
	"equipment_server/service/websocket"
	"errors"
	"fmt"
	"log"

	"time"

	mqtt "github.com/eclipse/paho.mqtt.golang" // 导入 MQTT 客户端库
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
)

// HandleDeviceResponse 是处理来自设备 MQTT 响应消息的函数
// 这个函数应该作为 MQTT 客户端的订阅回调函数被调用
func HandleDeviceResponse(client mqtt.Client, msg mqtt.Message) {
	// 打印日志，记录收到的设备响应消息的主题和 payload
	log.Printf("收到设备响应: topic=%s, payload=%s", msg.Topic(), msg.Payload())

	// 1. 解析 MQTT 响应 payload
	// 假设设备响应的 payload 是 JSON 格式，包含 request_id 和处理结果 (result: "approved" 或 "rejected")
	var responsePayload map[string]interface{}
	err := json.Unmarshal(msg.Payload(), &responsePayload)
	if err != nil {
		log.Printf("解析设备响应 payload 失败: %v", err)
		// 解析失败，无法继续处理，直接返回
		return
	}

	// 从 payload 中提取必要的字段
	requestID, ok := responsePayload["request_id"].(string)
	if !ok || requestID == "" {
		log.Printf("设备响应缺少 request_id 或格式错误")
		// 缺少关键信息，无法匹配请求，直接返回
		return
	}

	// 提取设备处理结果
	deviceResult, ok := responsePayload["result"].(string) // 假设设备返回 "approved" 或 "rejected"
	if !ok || (deviceResult != "approved" && deviceResult != "rejected") {
		log.Printf("设备响应缺少 result 或格式错误 (RequestID: %s). 期望 'approved' 或 'rejected', 实际 '%v'", requestID, responsePayload["result"])
		// 结果字段缺失或格式错误，无法确定设备意图，直接返回
		return
	}

	// 2. 查找对应的待处理请求
	// 根据 request_id 在 pending_binding_requests 集合中查找之前保存的待处理请求信息
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // 为数据库操作设置一个上下文超时
	defer cancel()                                                           // 确保上下文在函数退出时被取消

	pendingRequestsCollection := global.MonGoDatabase.Collection("pending_binding_requests")
	filter := bson.M{"request_id": requestID} // 根据 request_id 查找待处理请求

	var pendingReq model.PendingBindingRequest
	err = pendingRequestsCollection.FindOne(ctx, filter).Decode(&pendingReq)

	if errors.Is(err, mongo.ErrNoDocuments) {
		// 未找到对应的待处理请求。这可能意味着请求已超时并被清理，或者这是一个重复的设备响应
		log.Printf("未找到对应的待处理请求 (RequestID: %s). 可能已超时或重复响应.", requestID)
		return // 未找到请求，无需处理，直接返回
	} else if err != nil {
		// 查询待处理请求时发生其他数据库错误
		log.Printf("查询待处理请求失败 (RequestID: %s): %v", requestID, err)
		return // 数据库错误，无法处理，直接返回
	}

	// 如果找到了待处理请求 (pendingReq)，则根据其信息和设备响应结果进行处理

	// 3. 根据设备响应结果处理绑定/解绑逻辑
	bindingsCollection := global.MonGoDatabase.Collection("device_bindings") // 获取设备绑定集合

	switch pendingReq.RequestType {
	case "bind":
		// 处理绑定请求的设备响应
		if deviceResult == "approved" {
			// 设备同意绑定
			log.Printf("设备 %s 同意用户 %d 的绑定请求 (RequestID: %s)", pendingReq.DeviceID, pendingReq.UserID, requestID)

			// 在 device_bindings 集合中插入新的绑定记录
			newBinding := model.DeviceBinding{
				UserID:    pendingReq.UserID,
				DeviceID:  pendingReq.DeviceID,
				BoundTime: time.Now(), // 记录绑定成功的时间
			}
			_, err = bindingsCollection.InsertOne(ctx, newBinding)
			if err != nil {
				// 插入绑定记录失败
				log.Printf("保存设备绑定信息失败 (RequestID: %s): %v", requestID, err)
				websocket.GlobalHub.SendToUser(uint(pendingReq.UserID), "bind_result", false, "绑定失败（服务器内部错误）")
			} else {
				// 绑定记录插入成功
				log.Printf("用户 %d 成功绑定设备 %s (通过设备确认) (RequestID: %s). 绑定信息已保存", pendingReq.UserID, pendingReq.DeviceID, requestID)
				websocket.GlobalHub.SendToUser(uint(pendingReq.UserID), "bind_result", true, fmt.Sprintf("与%s设备绑定成功", pendingReq.DeviceID))
			}
		} else { // deviceResult == "rejected"
			// 设备拒绝绑定
			log.Printf("设备 %s 拒绝用户 %d 的绑定请求 (RequestID: %s)", pendingReq.DeviceID, pendingReq.UserID, requestID)
			websocket.GlobalHub.SendToUser(uint(pendingReq.UserID), "bind_result", false, "设备拒绝绑定")
		}

	case "unbind":
		// 处理解绑请求的设备响应
		if deviceResult == "approved" {
			// 设备同意解绑
			log.Printf("设备 %s 同意用户 %d 的解绑请求 (RequestID: %s)", pendingReq.DeviceID, pendingReq.UserID, requestID)
			// 从 device_bindings 集合中删除对应的绑定记录
			filter := bson.M{"user_id": pendingReq.UserID, "device_id": pendingReq.DeviceID} // 删除指定用户和设备的绑定记录
			deleteResult, err := bindingsCollection.DeleteOne(ctx, filter)
			if err != nil {
				// 删除绑定记录失败
				log.Printf("删除设备绑定信息失败 (RequestID: %s): %v", requestID, err)
				websocket.GlobalHub.SendToUser(uint(pendingReq.UserID), "unbind_result", false, "解绑失败 (服务器内部错误)")
			} else if deleteResult.DeletedCount == 0 {
				// 没有找到要删除的绑定记录。可能已经被其他方式解绑了。
				log.Printf("尝试删除用户 %d 设备 %s 的绑定信息，但未找到记录 (RequestID: %s).", pendingReq.UserID, pendingReq.DeviceID, requestID)
				websocket.GlobalHub.SendToUser(uint(pendingReq.UserID), "unbind_result", true, fmt.Sprintf("与%s设备解绑成功", pendingReq.DeviceID))
			} else {
				// 绑定记录删除成功
				log.Printf("用户 %d 成功解绑设备 %s (通过设备确认) (RequestID: %s). 绑定信息已删除", pendingReq.UserID, pendingReq.DeviceID, requestID)
				websocket.GlobalHub.SendToUser(uint(pendingReq.UserID), "unbind_result", true, fmt.Sprintf("与%s设备解绑成功", pendingReq.DeviceID))

			}
		} else { // deviceResult == "rejected"
			// 设备拒绝解绑
			log.Printf("设备 %s 拒绝用户 %d 的解绑请求 (RequestID: %s)", pendingReq.DeviceID, pendingReq.UserID, requestID)
			websocket.GlobalHub.SendToUser(uint(pendingReq.UserID), "unbind_result", false, "设备拒绝解绑")
		}

	default:
		// 如果 RequestType 不是 "bind" 也不是 "unbind"，说明待处理请求数据有问题
		log.Printf("待处理请求 (RequestID: %s) 的 RequestType 未知: %s", requestID, pendingReq.RequestType)
		websocket.GlobalHub.SendToUser(uint(pendingReq.UserID), "unbind_result", false, "系统繁忙")
	}

	// 4. 从待处理请求集合中删除已处理的请求
	// 不论设备是同意还是拒绝，只要收到了响应并处理完毕，就可以删除对应的待处理请求记录
	deleteResult, err := pendingRequestsCollection.DeleteOne(ctx, filter) // filter 是根据 request_id 查找的
	if err != nil {
		log.Printf("删除已处理待处理请求失败 (RequestID: %s): %v", requestID, err)
		// 删除失败不影响核心业务，记录日志即可
	} else if deleteResult.DeletedCount == 0 {
		// 理论上不应该发生，因为前面已经通过 FindOne 找到了记录
		log.Printf("未找到待处理请求进行删除 (RequestID: %s). 可能已被其他地方处理?", requestID)
	} else {
		log.Printf("已从待处理请求集合中删除请求 (RequestID: %s)", requestID)
	}
}
